﻿<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>

  <!-- Begin parameters declaration -->
  <xsl:param name="EnvironmentTarget" select="'EV1'" />
  <xsl:param name="ApplicationTarget" select="'PG2014_FULL'" />
  <!-- End parameters declaration -->

  <!-- Start deployment configuration creation -->
  <xsl:template match="/">
    <!-- Call deployment target -->
    <xsl:apply-templates select="//deploymentTarget[@environment=$EnvironmentTarget and @applicationName=$ApplicationTarget]" />
  </xsl:template>

  <!-- Create the deployment Target to use with applicationManagement Module v2-->
  <xsl:template match="//deploymentTarget">
    <deploymentTarget>
      <!-- Copy General deployer Configuration -->
      <xsl:apply-templates select="configuration" />

      <!-- Find application definition -->
      <xsl:variable name="application" select="//application[@name=$ApplicationTarget]" />

      <!-- Search Deployment Node -->
      <xsl:apply-templates select="deploymentNode">
        <xsl:with-param name="application" select="$application" />
      </xsl:apply-templates>

    </deploymentTarget>
  </xsl:template>

  <!-- Copy General configuration node whic contains logger configuration ans email configuration-->
  <xsl:template match="//configuration">
    <xsl:copy-of select="." />
  </xsl:template>

  <!-- Begin Apply template deploymentNode -->
  <xsl:template match ="//deploymentNode">
    <xsl:param name="application" />

    <xsl:variable name="serverName" select="@serverName" />

    <!-- Find Server configuration -->
    <xsl:variable name="server" select="//server[@name=$serverName]" />

    <xsl:comment>
      <xsl:text>Begin deployment node application </xsl:text>
      <xsl:value-of select="$application/@name"/> version <xsl:value-of select="$application/@version"/> on server <xsl:value-of select="@serverName"/>
    </xsl:comment>
    <server>
      <xsl:attribute name="name">
        <xsl:value-of select="@nodeName"/>
      </xsl:attribute>
      <!-- add server attribute -->
      <xsl:attribute name="hostName">
        <xsl:value-of select="$serverName"/>
      </xsl:attribute>
      <xsl:attribute name="environment">
        <xsl:value-of select="$EnvironmentTarget"/>
      </xsl:attribute>      
      <!-- Begin adding server Folder Attributes for application -->
      <xsl:apply-templates select="//folderTemplate[@name=$server/@applicationFolderTemplate]/folders/@*" mode="applicationFolder">
        <xsl:with-param name="application" select="$application" />
      </xsl:apply-templates>
      <!-- End adding server Folder Attributes for application -->

      <!-- Begin adding remote server Folder Attributes for application -->
      <xsl:apply-templates select="//folderTemplate[@name=$server/@remoteApplicationFolderStandard]/folders/@*" mode="remoteApplicationFolder">
        <xsl:with-param name="application" select="$application" />
        <xsl:with-param name="serverName" select="$serverName" />
      </xsl:apply-templates>
      <!-- End adding remote server Folder Attributes for application -->

      <!-- Begin adding server Folder Attributes -->
      <xsl:apply-templates select="//folderTemplate[@name=$server/@serverFolderTemplate]/folders/@*" mode="serverFolder" />
      <!-- End adding server Folder Attributes -->

      <!-- Begin adding winrm attributes -->
      <xsl:apply-templates select="//winRmTemplate[@name=$server/@winRmTemplate]/winRm/@*" mode="copyAttribute" />
      <!-- end Adding winrm attributes-->

      <!-- Begin adding products -->
      <xsl:apply-templates select="$server/products/product" />
      <!-- End adding products -->

      <!-- add components to be deployed -->
      <xsl:apply-templates select="component">
        <xsl:with-param name="server" select="$server" />
        <xsl:with-param name="application" select="$application" />
      </xsl:apply-templates>
    </server>

    <xsl:comment>
      <xsl:text>End deployment node application </xsl:text>
      <xsl:value-of select="$application/@name"/> version <xsl:value-of select="$application/@version"/> on server <xsl:value-of select="@serverName"/>
    </xsl:comment>
  </xsl:template>
  <!-- End Apply template deploymentNode -->

  <!-- Begin copy folders attribute with application name and version -->
  <xsl:template match="folders/@*" mode="applicationFolder">
    <xsl:param name="application" />

    <!-- attributeName -->
    <xsl:variable name="attributeName">
      <xsl:value-of select="name()"/>
    </xsl:variable>

    <xsl:attribute name="{$attributeName}">
      <xsl:call-template name="CreateServerFolderPathForApplication">
        <xsl:with-param name="folderPath" select="." />
        <xsl:with-param name="application" select="$application" />
        <xsl:with-param name="environment" select="$EnvironmentTarget" />
      </xsl:call-template>
    </xsl:attribute>

  </xsl:template>
  <!-- End copy folders attribute with application name and version -->

  <!-- Begin copy folders attribute with application name and version and create a folder definition for remote access -->
  <xsl:template match="folders/@*" mode="remoteApplicationFolder">
    <xsl:param name="application" />
    <xsl:param name="serverName" />


    <xsl:variable name="attributeValue">
      <xsl:call-template name="CreateServerFolderPathForApplication">
        <xsl:with-param name="folderPath" select="." />
        <xsl:with-param name="application" select="$application" />
        <xsl:with-param name="environment" select="$EnvironmentTarget" />
      </xsl:call-template>
    </xsl:variable>
    
    <!-- attributeName -->
    <xsl:variable name="attributeName">
      <xsl:value-of select="name()"/>
    </xsl:variable>

    <!-- Create UNC access for the server-->
    <xsl:variable name="UNCServer">
      <xsl:call-template name="EnsurePathEndTerminator">
        <xsl:with-param name="value" select="concat('\\', $serverName)"/>
      </xsl:call-template>
    </xsl:variable>

    <!-- Creater remote access with servername-->
    <xsl:attribute name="{$attributeName}">
      <xsl:value-of select="concat($UNCServer, $attributeValue)"/>
    </xsl:attribute>


  </xsl:template>
  <!-- end copy folders attribute with application name and version and create a remote access -->


  <!-- Begin copy folders attribute -->
  <xsl:template match="folders/@*" mode="serverFolder">

    <!-- attributeName -->
    <xsl:variable name="attributeName">
      <xsl:value-of select="name()"/>
    </xsl:variable>

    <xsl:attribute name="{$attributeName}">
      <xsl:call-template name="EnsurePathEndTerminator">
        <xsl:with-param name="value" select="." />
      </xsl:call-template>
    </xsl:attribute>

  </xsl:template>
  <!-- end copy folders attribute -->

  <!-- Begin create product component -->
  <xsl:template match="//server/products/product">
    <component>
      <!-- Copy attributes from the template -->
      <xsl:apply-templates select="@*" mode="copyAttribute" />

      <xsl:variable name="productName" select="@name" />
      
      <!-- Get product definition from products definition -->
      <xsl:apply-templates select="//productsRepository/product[@componentName=$productName]/@*" mode="copyAttribute" />
      
      <!-- Create dynamics properties -->
      <xsl:apply-templates select="//productsRepository/product[@componentName=$productName]/additionalParams">
        <xsl:with-param name="parent" select="." />
      </xsl:apply-templates>
      
      
    </component>
  </xsl:template>
  <!-- End create product component -->

  <xsl:template match="additionalParams">
    <xsl:param name="parent" />
    <xsl:attribute name="additionalParams">
      <xsl:apply-templates select="param">
        <xsl:with-param name="parent" select="$parent" />
      </xsl:apply-templates>
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="param">    
    <xsl:param name="parent" />
    <xsl:choose>
      <xsl:when test="@value">
        <xsl:value-of select="@value" />    
      </xsl:when>
      <xsl:when test="@relativeValue">
        <xsl:apply-templates select="." mode="GetRelativeValue">
          <xsl:with-param name="parent" select="$parent" />
        </xsl:apply-templates>
      </xsl:when>
    </xsl:choose>

    <xsl:apply-templates select="param">
      <xsl:with-param name="parent" select="$parent" />
    </xsl:apply-templates>
  </xsl:template>
  

  <!-- Begin Apply component for Server-->
  <xsl:template match="//deploymentNode/component">
    <xsl:param name="server" />
    <xsl:param name="application" />
    <xsl:variable name="componentName" select="@name" />
    <xsl:variable name="middlewareTarget" select="./@middlewareTarget"/>
    <xsl:variable name="applicationPoolTarget" select="./@applicationPoolTarget"/>

    <!-- Find component definition-->
    <xsl:variable name="component" select="$application/components/component[@name=$componentName]"/>

    <!-- Find Middleware definition -->
    <xsl:variable name="middleware" select="//server[@name=$server/@name]/middlewares/middleware[@type=$component/@middlewareTarget]/executionContainer[@name=$middlewareTarget]" />

    <!-- Find application pool definition -->
    <xsl:variable name="applicationPool" select="//server[@name=$server/@name]/middlewares/middleware[@type=$component/@middlewareTarget]/applicationPools/applicationPool[@applicationPoolName=$applicationPoolTarget]" />

    <component>
      <!-- Copy attributes from the template -->
      <xsl:apply-templates select="$component/@*" mode="copyAttribute" />

      <!-- Copy attributes from component instance -->
      <xsl:apply-templates select="./@*" mode="copyAttribute" />

      <!-- Add relative Attributes which are calculated with server Middleware execution container -->
      <xsl:apply-templates select="$component/relativeAttributes/*" mode="ApplyRelativeAttributeValue">
        <xsl:with-param name="parent" select="$middleware" />
      </xsl:apply-templates>

      <!-- add attributes from targeted application pool-->
      <xsl:apply-templates select="$applicationPool/@*" mode="copyAttribute" />

    </component>

  </xsl:template>
  <!-- End Apply component for Server-->

  <!-- Begin Apply template copy attributes from a node -->
  <xsl:template match="@*" mode="copyAttribute">
    <xsl:copy>
    </xsl:copy>
  </xsl:template>
  <!-- End Apply template component attributes to deployment node-->

  <!-- Begin Apply template component relative attributes to deployment node-->
  <xsl:template match="*" mode="ApplyRelativeAttributeValue">
    <xsl:param name="parent" />

    <!-- Attribute name come from the node name belong relativeAttributes-->
    <xsl:variable name="attributeName">
      <xsl:value-of select="name()"/>
    </xsl:variable>


    <!-- Concat targeted attribute value with relative value-->
    <xsl:attribute name="{$attributeName}">
      <xsl:apply-templates select="." mode="GetRelativeValue">
        <xsl:with-param name="parent" select="$parent" />
      </xsl:apply-templates>
    </xsl:attribute>

  </xsl:template>
  <!-- End Apply template component relative attributes to deployment node-->

  <xsl:template match="*" mode="GetRelativeValue">
    <xsl:param name="parent" />

    <!-- Read Targeted attribute Name to retrieve-->
    <xsl:variable name="targetedAttributeName">
      <xsl:value-of select="./@targetedAttributeName"/>
    </xsl:variable>

    <!-- Read Targeted attribute value on middleware-->
    <xsl:variable name="targetedAttributeValue">
      <xsl:value-of select="$parent/@*[name()=$targetedAttributeName]"/>
    </xsl:variable>

    <!-- Concat targeted attribute value with relative value-->
      <xsl:call-template name="EnsurePathEndTerminator">
        <xsl:with-param name="value" select="$targetedAttributeValue" />
        <xsl:with-param name="separator" select="./@separator" />
      </xsl:call-template>
      <xsl:if test="./@separator!=./@relativeValue">
        <xsl:value-of select="./@relativeValue"/>
      </xsl:if>

  </xsl:template>
  
  <!-- Function to Create a folder Path -->
  <xsl:template name="CreateServerFolderPathForApplication">
    <xsl:param name="folderPath" />
    <xsl:param name="application" />
    <xsl:param name="environment" />
    <xsl:param name="serverName" />


    <!-- String Folder Path\Application Name\Vversion-->
    <xsl:variable name="returnPath">
      <xsl:call-template name="EnsurePathEndTerminator">
        <xsl:with-param name="value" select="$folderPath" />
      </xsl:call-template>
      <xsl:value-of select="$environment" />\<xsl:value-of select="$application/@name"/>\V<xsl:value-of select="$application/@version"/>
    </xsl:variable>

    <!-- ensure last slash-->
    <xsl:call-template name="EnsurePathEndTerminator">
      <xsl:with-param name="value" select="$returnPath" />
    </xsl:call-template>
  </xsl:template>

  <!-- Function to ensure a separator at the end of a value -->
  <xsl:template name="EnsurePathEndTerminator">
    <xsl:param name="value" />
    <xsl:param name="separator" select="'\'" />

    <xsl:choose>
      <xsl:when test="$separator= substring($value, string-length($value) - string-length($separator) +1)">
        <xsl:value-of select="$value"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="returnValue">
          <xsl:value-of select="$value"/>
          <xsl:value-of select="$separator"/>
        </xsl:variable>
        <xsl:value-of select="$returnValue"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>
